﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Gakita.View.Menu
{
    class MenuView
    {
        public enum UserInput
        {
            Back,
            GoNextHighScore,
            GoPreviousHighScore,
            ChooseCurrent,
            ChangeUp,
            ChangeDown,
            Nothing,
        }

        private SpriteBatch _spriteBatch;
        private Texture2D _menuBackgroundTexture;
        private KeyboardState _oldKeyboardState;
        private SpriteFont _menuFont;
        private SpriteFont _smallMenuFont;
        private Song _menuSong;
        private GraphicsDeviceManager _graphicsDeviceManager;

        private static bool _isMenuSongPlaying                      =       false;

        public MenuView(GraphicsDeviceManager aManager, ContentManager aContentManager, SpriteBatch _aSpriteBatch)
        {
            _spriteBatch = _aSpriteBatch;
            _oldKeyboardState = new KeyboardState(Keys.Enter);
            _graphicsDeviceManager = aManager;

            _menuFont = aContentManager.Load<SpriteFont>("MenuFont");
            _smallMenuFont = aContentManager.Load<SpriteFont>("smallMenuFont");
            _menuSong = aContentManager.Load<Song>("aurainprogress");
            _menuBackgroundTexture = aContentManager.Load<Texture2D>("menuBackground");

        }

        public void DrawMenu(MenuModel.MenuOptions[] aMenuOptions, MenuModel.MenuOptions aSelectedMenuOption, bool aGameIsRunning,                                        MenuModel.MenuOptions keyChanging, List<List<HighScore>> aHighScores, Controller.MenuController.State aState)
        {
            if (_isMenuSongPlaying == false)
            {
                MediaPlayer.Play(_menuSong);
                _isMenuSongPlaying = true;
                GameView.StopBackgroundMusic();
            }
            
            _graphicsDeviceManager.GraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(142, 255, 255));

            Vector2 viewportSize = new Vector2(_graphicsDeviceManager.GraphicsDevice.Viewport.Width,                                                                                        _graphicsDeviceManager.GraphicsDevice.Viewport.Height);

            _spriteBatch.Begin();

            DrawBackground(viewportSize);

            foreach (View.Menu.MenuModel.MenuOptions menuOption in aMenuOptions)
            {
                //Draw the selected alternative in red
                if ((int)menuOption == (int)aSelectedMenuOption)
                {
                    DrawMenuOption(viewportSize, menuOption, Color.Red, aGameIsRunning, _graphicsDeviceManager, keyChanging);
                }
                //Draw the other alternatives
                else
                {
                    DrawMenuOption(viewportSize, menuOption, Color.Black, aGameIsRunning, _graphicsDeviceManager, keyChanging);
                }
            }
            if (aState == Controller.MenuController.State.SelectLevel)
            {
                DrawBestTimesForEachLevel(aHighScores, viewportSize);
            }
            _spriteBatch.End();
        }

        public void DrawHighScores(GraphicsDevice aGraphicsDevice, List<Menu.HighScore> aHighScores, int currentHighScore)
        {
            //Background color
            aGraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(142, 255, 255));

            Vector2 viewportSize = new Vector2(aGraphicsDevice.Viewport.Width, aGraphicsDevice.Viewport.Height);

            _spriteBatch.Begin();
            
            DrawHighScore(viewportSize, aHighScores, currentHighScore);

            _spriteBatch.End();
        }


        public void DrawHighScore(Vector2 aViewportSize,List<Menu.HighScore> aHighScores, int level)
        {
            if (aHighScores.Count() == 0)
            {
                DrawLoading(aViewportSize);
            }
            else
            {
                DrawHighScoreObjectHeader(aViewportSize);
                foreach(Menu.HighScore highscore in aHighScores)
                {
                    DrawHighScoreObject(aViewportSize, highscore);
                }
                DrawLevelText(aViewportSize,level);
            }
        }

        private void DrawBestTimesForEachLevel(List<List<HighScore>> aHighScores, Vector2 aViewportSize)
        {
            int list = 1;
            foreach(List<HighScore> aList in aHighScores)
            {
                string highscoreString = "Best Time: ";
                if(aList.Count() == 0)
                {
                    highscoreString += "Loading...";
                }
                else
                {
                    highscoreString += aList.First().GetName() + ", ";
                    String time = ((double)aList.First().GetTime() / 1000).ToString().Substring(0, 5) + " seconds";
                    highscoreString += time;
                }

                Vector2 textPosition = new Vector2(aViewportSize.X / 2 - _smallMenuFont.MeasureString(highscoreString).X/2, 
                                                   aViewportSize.Y / 6f * list + _smallMenuFont.MeasureString(highscoreString).Y);

                _spriteBatch.DrawString(_smallMenuFont, highscoreString, textPosition, Color.Fuchsia);

                list ++;
            }
        }

        private void DrawLevelText(Vector2 aViewportSize, int level)
        {
            string text = "";

            switch (level)
            {
                case 1:
                    text = "< First Level >";
                    break;
                case 2:
                    text = "< Second Level >";
                    break;
                case 3:
                    text = "< Third Level >";
                    break;
                case 4:
                    text = "< Fourth Level >";
                    break;
            }

            Vector2 textPosition = new Vector2(aViewportSize.X / 2 - _menuFont.MeasureString(text).X / 2, 0);

            _spriteBatch.DrawString(_menuFont, text, textPosition, Color.Black);
        }

        private void DrawHighScoreObjectHeader(Vector2 aViewportSize)
        {
            String rank = "Rank";
            String name = "Name";
            String time = "Time";

            Vector2 rankPosition = new Vector2(0 + aViewportSize.X / 8, aViewportSize.Y / 12);
            Vector2 namePosition = new Vector2(0 + aViewportSize.X / 8 * 3, aViewportSize.Y / 12);
            Vector2 timePosition = new Vector2(0 + aViewportSize.X / 8 * 5, aViewportSize.Y / 12);

            _spriteBatch.DrawString(_menuFont, rank, rankPosition, Color.Black);
            _spriteBatch.DrawString(_menuFont, name, namePosition, Color.Black);
            _spriteBatch.DrawString(_menuFont, time, timePosition, Color.Black);
        }

        public void DrawHighScoreObject(Vector2 aViewportSize,Menu.HighScore aHighScore)
        {
            String rank = aHighScore.GetRank().ToString();
            String name = aHighScore.GetName();
            String time = ((double)aHighScore.GetTime() / 1000).ToString().Substring(0, 5) + " seconds"; 

            Vector2 rankPosition = new Vector2(0 + aViewportSize.X / 8, aViewportSize.Y / 12 * (aHighScore.GetRank() + 1));
            Vector2 namePosition = new Vector2(0 + aViewportSize.X / 8 * 3, aViewportSize.Y / 12 * (aHighScore.GetRank() + 1));
            Vector2 timePosition = new Vector2(0 + aViewportSize.X / 8 * 5, aViewportSize.Y / 12 * (aHighScore.GetRank() + 1));

            _spriteBatch.DrawString(_menuFont, rank, rankPosition, Color.DeepPink);
            _spriteBatch.DrawString(_menuFont, name, namePosition, Color.DeepPink);
            _spriteBatch.DrawString(_menuFont, time, timePosition, Color.DeepPink);
        }

        public void DrawLoading(Vector2 aViewportSize)
        {
            String text = "Loading...";

            Vector2 textPosition = new Vector2(aViewportSize.X/2 - _menuFont.MeasureString(text).X / 2,aViewportSize.Y/2 -                                                                  _menuFont.MeasureString(text).Y /2 );

            _spriteBatch.DrawString(_menuFont, text, textPosition, Color.Black);
        }

        public void DrawMenuOption(Vector2 aViewportSize, MenuModel.MenuOptions aMenuOption, Color aColor, bool aGameIsRunning,                                                 GraphicsDeviceManager aGraphicsDevice, MenuModel.MenuOptions keyChanging)
        {
            string menuString = null;
            string endString = "_";

            //Set the menuoption text
            switch (aMenuOption)
            {
                case View.Menu.MenuModel.MenuOptions.NewGame:
                    if (aGameIsRunning == true)
                    {
                        menuString = "Resume Game";
                    }
                    else
                    {
                        menuString = "New Game";
                    }
                    break;
                case View.Menu.MenuModel.MenuOptions.SelectLevel:
                    menuString = "Select Level";
                    break;
                case View.Menu.MenuModel.MenuOptions.BestTimes:
                    menuString = "Best Times";
                    break;
                case View.Menu.MenuModel.MenuOptions.Options:
                    menuString = "Options";
                    break;
                case View.Menu.MenuModel.MenuOptions.ExitGame:
                    menuString = "Exit";
                    break;
                case View.Menu.MenuModel.MenuOptions.FullScreen:
                    string fullScreenIsOn = "Off";
                    if (_graphicsDeviceManager.IsFullScreen == true)
                    {
                        fullScreenIsOn = "On";
                    }
                    menuString = "Full Screen: " + fullScreenIsOn;
                    break;
                case View.Menu.MenuModel.MenuOptions.JumpKey:
                    if (keyChanging != MenuModel.MenuOptions.JumpKey)
                    {
                        endString = View.GameView.GetJumpKey().ToString();
                    }

                    menuString = "Jump Key: " + endString;
                    break;
                case View.Menu.MenuModel.MenuOptions.LeftKey:
                    if (keyChanging != MenuModel.MenuOptions.LeftKey)
                    {
                        endString = View.GameView.GetLeftKey().ToString();
                    }

                    menuString = "Left Key: " + endString;
                    break;
                case View.Menu.MenuModel.MenuOptions.RightKey:
                    if (keyChanging != MenuModel.MenuOptions.RightKey)
                    {
                        endString = View.GameView.GetRightKey().ToString();
                    }
  
                    menuString = "Right Key: " + endString;
                    break;
                case View.Menu.MenuModel.MenuOptions.FirstLevel:
                    menuString = "First Level";
                    break;
                case View.Menu.MenuModel.MenuOptions.SecondLevel:
                    menuString = "Second Level";
                    break;
                case View.Menu.MenuModel.MenuOptions.ThirdLevel:
                    menuString = "Third Level";
                    break;
                case View.Menu.MenuModel.MenuOptions.FourthLevel:
                    menuString = "Fourth Level";
                    break;
            }

            //Find Position
            Vector2 textSize = _menuFont.MeasureString(menuString);
            float verticalPosition = 0;

            if ((int)aMenuOption < 6)
            {
                verticalPosition = (aViewportSize.Y / 6) * (int)aMenuOption - textSize.Y / 2;
            }
            else if ((int)aMenuOption < 10)
            {
                verticalPosition = (aViewportSize.Y / 6) * ((int)aMenuOption - 5) - textSize.Y / 2;
            }
            else
            {
                verticalPosition = (aViewportSize.Y / 6) * ((int)aMenuOption - 9) - textSize.Y / 2;
            }
            Vector2 textPosition = new Vector2((aViewportSize.X / 2 - textSize.X/2), verticalPosition);

            //Draw the menuoption
            _spriteBatch.DrawString(_menuFont, menuString, textPosition, aColor);
        }

        public void DrawBackground(Vector2 aViewPortSize)
        {
            Rectangle destinationRectangle = new Rectangle(0,0,(int)aViewPortSize.X,(int)aViewPortSize.Y);

            _spriteBatch.Draw(_menuBackgroundTexture, destinationRectangle, Color.White);
        }

        public UserInput GetUserMenuInput()
        {  
            KeyboardState newKeyboardState = Keyboard.GetState();

            UserInput ret = UserInput.Nothing;

            if (_oldKeyboardState.IsKeyUp(Keys.Space) && newKeyboardState.IsKeyDown(Keys.Space) ||
                _oldKeyboardState.IsKeyUp(Keys.Enter) && newKeyboardState.IsKeyDown(Keys.Enter))
            {
                ret = UserInput.ChooseCurrent;
            }
            else if (_oldKeyboardState.IsKeyDown(Keys.Down) && newKeyboardState.IsKeyUp(Keys.Down))
            {
                ret = UserInput.ChangeDown;
            }
            else if (_oldKeyboardState.IsKeyDown(Keys.Up) && newKeyboardState.IsKeyUp(Keys.Up))
            {
                ret = UserInput.ChangeUp;
            }

            _oldKeyboardState = newKeyboardState;

            return ret;
        }

        public UserInput GetUserHighScoreInput()
        {
            KeyboardState newKeyboardState = Keyboard.GetState();

            UserInput ret = UserInput.Nothing;

            if (_oldKeyboardState.IsKeyDown(Keys.Left) && newKeyboardState.IsKeyUp(Keys.Left))
            {
                ret = UserInput.GoPreviousHighScore;
            }
            else if (_oldKeyboardState.IsKeyDown(Keys.Right) && newKeyboardState.IsKeyUp(Keys.Right))
            {
                ret = UserInput.GoNextHighScore;
            }
            else if (_oldKeyboardState.IsKeyDown(Keys.Escape) && newKeyboardState.IsKeyUp(Keys.Escape))
            {
                ret = UserInput.Back;
            }

            _oldKeyboardState = newKeyboardState;

            return ret;
        }


        public bool ChangeAKey(MenuModel.MenuOptions aMenuOption)
        {
            Keys[] validinput = new Keys[37] { Keys.A, Keys.B, Keys.C, Keys.D, Keys.E, Keys.F, Keys.G, Keys.H, Keys.I, Keys.J, Keys.K,                                                      Keys.L, Keys.M, Keys.N, Keys.O, Keys.P, Keys.Q, Keys.R, Keys.S, Keys.T, Keys.U, Keys.V,                                                      Keys.W, Keys.Z, Keys.X , Keys.Right, Keys.Left, Keys.Up, Keys.Down, Keys.LeftShift,                                                          Keys.RightShift, Keys.RightControl, Keys.LeftControl, Keys.CapsLock, Keys.Tab, Keys.Back,                                                    Keys.Space };

            bool ret = false;

            KeyboardState newKeyboardState = Keyboard.GetState();

            foreach (Keys key in validinput)
            {
                if (_oldKeyboardState.IsKeyDown(key) && newKeyboardState.IsKeyUp(key))
                {
                    ret = true;
                    switch(aMenuOption)
                    {
                        case MenuModel.MenuOptions.JumpKey:
                            View.GameView.SetJumpKey(key);
                            break;
                        case MenuModel.MenuOptions.LeftKey:
                            View.GameView.SetLeftKey(key);
                            break;
                        case MenuModel.MenuOptions.RightKey:
                            View.GameView.SetRightKey(key);
                            break;
                    }
                        
                }
            }
            _oldKeyboardState = newKeyboardState;

            return ret;
        }

        public static void StopMenuMusic()
        {
            _isMenuSongPlaying = false;
        }
    }
}
